<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
    <title>WebGPU Multisampling - center issue</title>
    <style>
      @import url(resources/webgpu-lesson.css);
html, body {
  margin: 0;       /* remove the default margin          */
  height: 100%;    /* make the html,body fill the page   */
}
canvas {
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  display: block;  /* make the canvas act like a block   */
  width: 100%;     /* make the canvas fill its container */
  height: 100%;
}
    </style>
  </head>
  <body>
    <canvas></canvas>
  </body>
  <script type="module">
async function main() {
  const adapter = await navigator.gpu?.requestAdapter();
  const device = await adapter?.requestDevice();
  if (!device) {
    fail('need a browser that supports WebGPU');
    return;
  }

  // Get a WebGPU context from the canvas and configure it
  const canvas = document.querySelector('canvas');
  const context = canvas.getContext('webgpu');
  const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
  context.configure({
    device,
    format: presentationFormat,
  });

  const module = device.createShaderModule({
    label: 'our hardcoded red triangle shaders',
    code: /* wgsl */ `
      struct VOut {
        @builtin(position) position: vec4f,
        @location(0) baryCoord: vec3f,
      };

      @vertex fn vs(
        @builtin(vertex_index) vertexIndex : u32
      ) -> VOut {
        let pos = array(
          vec2f( 0.0,  0.5),  // top center
          vec2f(-0.5, -0.5),  // bottom left
          vec2f( 0.5, -0.5)   // bottom right
        );
        let bary = array(
          vec3f(1, 0, 0),
          vec3f(0, 1, 0),
          vec3f(0, 0, 1),
        );
        var vout: VOut;
        vout.position = vec4f(pos[vertexIndex], 0.0, 1.0);
        vout.baryCoord = bary[vertexIndex];
        return vout;
      }

      @fragment fn fs(vin: VOut) -> @location(0) vec4f {
        let allAbove0 = all(vin.baryCoord >= vec3f(0));
        let allBelow1 = all(vin.baryCoord <= vec3f(1));
        let inside = allAbove0 && allBelow1;
        let red = vec4f(1, 0, 0, 1);
        let yellow = vec4f(1, 1, 0, 1);
        return select(yellow, red, inside);
      }
    `,
  });

  const pipeline = device.createRenderPipeline({
    label: 'our hardcoded red triangle pipeline',
    layout: 'auto',
    vertex: {
      module,
    },
    fragment: {
      module,
      targets: [{ format: presentationFormat }],
    },
    multisample: {
      count: 4,
    },
  });

  const renderPassDescriptor = {
    label: 'our basic canvas renderPass',
    colorAttachments: [
      {
        // view: <- to be filled out when we render
        clearValue: [0.3, 0.3, 0.3, 1],
        loadOp: 'clear',
        storeOp: 'store',
      },
    ],
  };

  let multisampleTexture;

  function render() {
    // Get the current texture from the canvas context
    const canvasTexture = context.getCurrentTexture();

    // If the multisample texture doesn't exist or
    // is the wrong size then make a new one.
    if (!multisampleTexture ||
        multisampleTexture.width !== canvasTexture.width ||
        multisampleTexture.height !== canvasTexture.height) {

      // If we have an existing multisample texture destroy it.
      if (multisampleTexture) {
        multisampleTexture.destroy();
      }

      // Create a new multisample texture that matches our
      // canvas's size
      multisampleTexture = device.createTexture({
        format: canvasTexture.format,
        usage: GPUTextureUsage.RENDER_ATTACHMENT,
        size: [canvasTexture.width, canvasTexture.height],
        sampleCount: 4,
      });
    }

    // Set the multisample texture as the texture to render to
    renderPassDescriptor.colorAttachments[0].view =
        multisampleTexture.createView();
    // Set the canvas texture as the texture to "resolve"
    // the multisample texture to.
    renderPassDescriptor.colorAttachments[0].resolveTarget =
        canvasTexture.createView();

    const encoder = device.createCommandEncoder({ label: 'our encoder' });
    const pass = encoder.beginRenderPass(renderPassDescriptor);
    pass.setPipeline(pipeline);
    pass.draw(3);  // call our vertex shader 3 times
    pass.end();

    const commandBuffer = encoder.finish();
    device.queue.submit([commandBuffer]);
  }

  const observer = new ResizeObserver(entries => {
    for (const entry of entries) {
      const canvas = entry.target;
      const width = entry.contentBoxSize[0].inlineSize / 16 | 0;
      const height = entry.contentBoxSize[0].blockSize / 16 | 0;
      canvas.width = Math.max(1, Math.min(width, device.limits.maxTextureDimension2D));
      canvas.height = Math.max(1, Math.min(height, device.limits.maxTextureDimension2D));
      // re-render
      render();
    }
  });
  observer.observe(canvas);
}

function fail(msg) {
  // eslint-disable-next-line no-alert
  alert(msg);
}

main();
  </script>
</html>
